home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC]
/
NeXTSTEP 3.3 Dev Intel.iso
/
NextDeveloper
/
Source
/
GNU
/
cctools
/
as
/
sections.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-03
|
8KB
|
251 lines
/* sections.c (was subsegs.c in original GAS version)
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Mach-O sections are chains of fragments.
*/
#include <stdlib.h>
#include <strings.h>
#include "sections.h"
#include "obstack.h"
#include "xmalloc.h"
#include "frags.h"
#include "messages.h"
/*
* All sections' chains hang off here. NULL means no frchains yet.
*/
frchainS *frchain_root = NULL;
/*
* The frchain we are assembling into now. That is, the current section's
* frag chain, even if it contains no (complete) frags.
*/
frchainS *frchain_now = NULL;
/*
* sections_begin() sets up to allow sections to be created.
*/
void
sections_begin(
void)
{
/* This may be needed if a section_new() for .text is not assumed */
/* obstack_begin(&frags, 5000); */
/* frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); */
}
/*
* section_new() (for non-zerofill sections) switches to a new section, creating
* it if needed, and creates a fresh fragment. If it is the current section
* nothing happens except checks to make sure the type, attributes and
* sizeof_stub are the same. The segment and section names will be trimed to
* fit in the section structure and is the responsiblity of the caller to
* report errors if they don't. For zerofill sections only the struct frchain
* for the section is returned after possibly being created (these section are
* never made the current section and no frags are ever touched).
*
* Globals on input:
* frchain_now points to the (possibly none) struct frchain for the current
* section.
* frag_now points at an incomplete frag for current section.
* If frag_now == NULL, then there is no old, incomplete frag, so the old
* frag is not closed off.
*
* Globals on output:
* frchain_now points to the (possibly new) struct frchain for this section.
* frchain_root updated if needed (for the first section created).
* frag_now is set to the last (possibly new) frag in the section.
*/
frchainS *
section_new(
char *segname,
char *sectname,
unsigned long type,
unsigned long attributes,
unsigned long sizeof_stub)
{
frchainS *frcP;
frchainS **lastPP;
unsigned long last_nsect;
if(frags.chunk_size == 0)
/*
* This line is use instead of:
* obstack_begin(&frags, 5000);
* which the only difference is that frags are allocated on 4 byte
* boundaries instead of the default. The problem with the default
* is that on some RISC machines the obstack uses 8 (the alignment
* of a double after a char in a struct) and then the common use of:
* frag_now->fr_fix = obstack_next_free(&frags) -
* frag_now->fr_literal;
* can get an extra 4 bytes that are not in the frag because of the
* 8 byte alignment where only 4 byte alignment for frags are
* needed.
*/
_obstack_begin(&frags, 5000, 4,
obstack_chunk_alloc, obstack_chunk_free);
/*
* Determine if this section has been seen.
*/
last_nsect = 0;
for(frcP = *(lastPP = &frchain_root);
frcP != NULL;
frcP = *(lastPP = &frcP->frch_next)){
if(strncmp(frcP->frch_section.segname, segname,
sizeof(frcP->frch_section.segname)) == 0 &&
strncmp(frcP->frch_section.sectname, sectname,
sizeof(frcP->frch_section.sectname)) == 0)
break;
last_nsect = frcP->frch_nsect;
}
/*
* If this section has been seen make sure it's type and attributes
* for this call are the same as when the section was created.
*/
if(frcP != NULL){
if((frcP->frch_section.flags & SECTION_TYPE) != type){
as_warn("section type does not match previous section type");
}
if(type == S_SYMBOL_STUBS &&
frcP->frch_section.reserved2 != sizeof_stub){
as_warn("section stub size does not match previous section "
"stub size");
}
if((frcP->frch_section.flags & SECTION_ATTRIBUTES) != attributes){
as_warn("section attributes does not match previous section "
"attributes");
}
}
/*
* If the current section is the same as for this call there is nothing
* more to do.
*/
if(frcP != NULL && (frchain_now == frcP || type == S_ZEROFILL)){
return(frcP);
}
/*
* For non-zerofill sections it will be made the current section so deal
* with the current frag.
*/
if(type != S_ZEROFILL){
/*
* If there is any current frag in the old section close it off.
*/
if(frag_now != NULL){
frag_now->fr_fix = obstack_next_free(&frags) -
frag_now->fr_literal;
frag_wane(frag_now);
}
/*
* We must do the obstack_finish(), so the next object we put on
* obstack frags will not appear to start at the fr_literal of the
* current frag. Also, it ensures that the next object will begin
* on a address that is aligned correctly for the engine that runs
* the assembler.
*/
obstack_finish(&frags);
}
/*
* If this section exists since it is not the current section switch to
* it by making it the current chain and create a new frag in it.
*/
if(frcP != NULL){
/*
* For a zerofill section no frags are created here and since it
* exist just return a pointer to the section.
*/
if((frcP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL){
return(frcP);
}
else{
/*
* Make this section the current section.
*/
frchain_now = frcP;
/*
* Make a fresh frag for the section.
*/
frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
frag_now->fr_next = NULL;
/*
* Append the new frag to the existing frchain.
*/
frchain_now->frch_last->fr_next = frag_now;
frchain_now->frch_last = frag_now;
}
}
else{
/*
* This section does not exist so create a new frchainS struct fill
* it in, link it to the chain
*/
frcP = (frchainS *)xmalloc(sizeof(frchainS));
memset(frcP, '\0', sizeof(frchainS));
strncpy(frcP->frch_section.segname, segname,
sizeof(frcP->frch_section.segname));
strncpy(frcP->frch_section.sectname, sectname,
sizeof(frcP->frch_section.sectname));
frcP->frch_section.flags = attributes | type;
frcP->frch_section.reserved2 = sizeof_stub;
frcP->frch_nsect = last_nsect + 1;
*lastPP = frcP;
/*
* For zerofill sections no frag is created here so just return.
* For non-zerofill section create the sections new frag and
* make the section the current chain.
*/
if(type == S_ZEROFILL){
return(frcP);
}
else{
/*
* Make a fresh frag for the new section.
*/
frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
frag_now->fr_next = NULL;
/*
* Append the new frag to new frchain.
*/
frcP->frch_root = frag_now;
frcP->frch_last = frag_now;
/*
* Make this section the current section.
*/
frchain_now = frcP;
}
}
return(frchain_now);
}